package org.xmap.ui.control;

import java.util.Vector;
import javax.microedition.lcdui.*;
import org.xmap.app.Env;
import org.xmap.ui.base.*;
import org.xmap.ui.listener.ItemListener;

/**
 * <p>图片列表类，用于显示大量的小图片的控件。</p>
 * @author Zealot
 * @version 1.0
 */
public final class ImageGrid extends Window {

    /**
     * 图片块的拉伸模式。
     */
    private int scretchMode;
    /**
     * 存储小图片的信息。
     */
    private Vector content;
    /**
     * 内容占用的位置大小，单位为象素。
     */
    private int cellWidth;
    /**
     * 当前选中的横坐标。
     */
    private int xIndex;
    /**
     * 当前选中的纵坐标。
     */
    private int yIndex;
    /**
     * 图像被选中的监听器。
     */
    private ItemListener itemListener;
    /**
     * 是否显示边框。
     */
    private boolean drawRect;
    /**
     * 是否是透明，如果透明，将不会显示背景颜色。
     */
    private boolean transparent;
    /**
     * 当前显示的内容的第一行在整个content中的位置。
     */
    private int drawBase;
    /**
     * 横方向显示的图片的个数。
     */
    private int xDisCount;
    /**
     * 纵方向显示的图片的个数。
     */
    private int yDisCount;
    /**
     * 横方向的绘制偏移。
     */
    private int xDisOffset;
    /**
     * 纵方向的绘制偏移。
     */
    private int yDisOffset;
    /**
     * 边框的颜色。
     */
    private int lineColor;
    /**
     * 滚动条边框的颜色。
     */
    private int strollbarLineColor;
    /**
     * 滚动条的颜色。
     */
    private int strollbarColor;
    /**
     * 选中的颜色。
     */
    private int selectedColor;
    /**
     * 触笔按下的时候选中的序号。
     */
    private int pressSelectedIndex;
    /**
     * 有效的宽度，除去右侧滚动条的宽度。
     */
    private int effectiveWidth;
    /**
     * 滚动条的y坐标。
     */
    private int strollY;
    /**
     * 滚动条的高度。
     */
    private int strollHeight;
    /**
     * 触笔选中滚动条的时候，上下移动触笔strollRowHeight个像素，将导致文本区域移动。
     */
    private int strollRowHeight;
    /**
     * 左侧除去滚动条的区域。
     */
    private Rect leftRect;

    /**
     * 指定锚点横坐标、纵坐标、图像组宽度、图像组高度、图像块间隔和锚点类型的构造函数。
     * @param x int 锚点横坐标。
     * @param y int 锚点纵坐标。
     * @param width int 图像组宽度。
     * @param height int 图像组高度。
     * @param cellWidth int 图像块间隔。
     * @param orient int 锚点类型。
     */
    public ImageGrid(int x, int y, int width, int height, int cellWidth, int orient) {
        super(x, y, width, height, orient);
        super.setCanFocus(true);
        this.scretchMode = 0;
        this.content = new Vector(32);
        this.cellWidth = cellWidth;
        this.xIndex = -1;
        this.yIndex = -1;
        this.itemListener = null;
        this.drawRect = false;
        this.transparent = true;
        this.drawBase = 0;
        this.lineColor = 0xffff0000;
        this.strollbarLineColor = 0xFF1BA0D8;
        this.strollbarColor = 0xFFFCA432;
        this.selectedColor = 0xffff0000;
        this.leftRect = new Rect(this.getRect());
        this.calcuateView();
    }

    /**
     * 设置文本区域的窗口区域。
     * @param leftUpX int 文本区域左上角横坐标。
     * @param leftUpY int 文本区域左上角纵坐标。
     * @param width int 文本区域宽度。
     * @param height int 文本区域高度。
     */
    public void setRect(int leftUpX, int leftUpY, int width, int height) {
        super.setRect(leftUpX, leftUpY, width, height);
        this.calcuateView();
    }

    /**
     * 设置图片块的拉伸模式。
     * @param scretchMode int 拉伸模式。
     */
    public void setScretchMode(int scretchMode) {
        if (scretchMode <= 3) {
            this.scretchMode = scretchMode;
            if (this.scretchMode != 0) {
                this.sizeChanged(Env.instance.screenWidth, Env.instance.screenHeight);
            }
        }
    }

    /**
     * 获得图片块的拉伸模式。
     * @return int 拉伸模式。
     */
    public int getScretchMode() {
        return this.scretchMode;
    }

    /**
     * 屏幕发生改变的通知。
     * @param width int 新的屏幕宽度。
     * @param height int 新的屏幕高度。
     */
    public void sizeChanged(int width, int height) {
        boolean calcuateView = false;
        if ((this.scretchMode & Window.SCRETCH_ROW) > 0) { // 横向扩展
            this.getRect().leftUp.x = 0;
            if (this.getRect().width != width) {
                this.getRect().width = width;
                calcuateView = true;
            }
        }
        if ((this.scretchMode & Window.SCRETCH_COLUMN) > 0) { // 纵向扩展
            if (this.owner != null) {
                this.getRect().leftUp.y = 0;
                if (this.getRect().height != this.owner.getClientRect().height) {
                    this.getRect().height = this.owner.getClientRect().height;
                    calcuateView = true;
                }
            }
        }
        if (calcuateView) {
            this.calcuateView();
        }
    }

    /**
     * 向图片块控件添加数据。
     * @param id int 图片块被选中的时候，将会在回调时，作为第一个参数。
     * @param obj Object 图片块被选中的时候，将会在回调时，作为第二个参数。
     * @param img Image 图片数据。
     */
    public void addContent(int id, Object obj, Object img) {
        ListItem li = new ListItem(id, obj, img, null, null, null, null, null);
        this.content.addElement(li);
        if (this.xIndex == -1 && this.yIndex == -1) {
            this.xIndex = 0;
            this.yIndex = 0;
        }
        if (this.content.size() == 1 && this.itemListener != null) {
            this.itemListener.keySelected(id, obj);
        }
        this.calcuateStrollbar();
    }

    /**
     * 设置按键事件导致图片被选中的监听器。
     * @param isl ItemSelectListener 监听器。
     */
    public void setItemListener(ItemListener il) {
        this.itemListener = il;
        if (this.content.size() > 0 && super.getFocus()) {
            int index = this.getSelectIndex();
            if (index > 0) {
                ListItem li = (ListItem) this.content.elementAt(index);
                if (li != null) {
                    this.itemListener.keySelected(li.id, li.obj);
                }
            }
        }
    }

    /**
     * 设置是否显示边框。
     * @param drawRect boolean 是否显示边框。
     */
    public void setDrawRect(boolean drawRect) {
        this.drawRect = drawRect;
    }

    /**
     * 获得是否显示边框。
     * @return boolean 是否显示边框。
     */
    public boolean getDrawRect() {
        return this.drawRect;
    }

    /**
     * 设置图像块是否为透明，透明的意思是不用背景颜色填充背景。
     * @param transparent boolean 是否透明。
     */
    public void setTransparent(boolean transparent) {
        this.transparent = transparent;
    }

    /**
     * 获得图像块是否为透明。
     * @return boolean 是否透明。
     */
    public boolean getTransparent() {
        return this.transparent;
    }

    /**
     * 设置边框的颜色。
     * @param lineColor int 边框颜色。
     */
    public void setLineColor(int lineColor) {
        this.lineColor = lineColor;
    }

    /**
     * 获得边框的颜色。
     * @return int 边框颜色。
     */
    public int getLineColor() {
        return this.lineColor;
    }

    /**
     * 设置滚动条边框的颜色。
     * @param strollbarLineColor int 边框的颜色。
     */
    public void setStrollbarLineColor(int strollbarLineColor) {
        this.strollbarLineColor = strollbarLineColor;
    }

    /**
     * 获得滚动条边框的颜色。
     * @return int 滚动条边框的颜色。
     */
    public int getStrollbarLineColor() {
        return this.strollbarLineColor;
    }

    /**
     * 设置滚动条的颜色。
     * @param strollbarColor int 滚动条的颜色。
     */
    public void setStrollbarColor(int strollbarColor) {
        this.strollbarColor = strollbarColor;
    }

    /**
     * 获得滚动条的颜色。
     * @return int 滚动条的颜色。
     */
    public int getStrollbarColor() {
        return this.strollbarColor;
    }

    /**
     * 设置选中的颜色。
     * @param selectedColor int 选中的颜色。
     */
    public void setSelectedColor(int selectedColor) {
        this.selectedColor = selectedColor;
    }

    /**
     * 获得选中的颜色。
     * @return int 选中的颜色。
     */
    public int getSelectedColor() {
        return this.selectedColor;
    }

    /**
     * 获得选中的序号。
     * @return int 选中的序号。
     */
    public int getSelectIndex() {
        if (this.xIndex != -1 && this.yIndex != -1) {
            return (this.drawBase + this.yIndex) * this.xDisCount + this.xIndex;
        }
        return -1;
    }

    /**
     * 获得当前选中图片的id。
     * @return int 当前选中图片的id。
     */
    public int getSelectId() {
        int index = this.getSelectIndex();
        if (index > 0) {
            ListItem li = (ListItem) this.content.elementAt(index);
            if (li != null) {
                return li.id;
            }
        }
        return -1;
    }

    /**
     * 获得当前选中图片的对象。
     * @return Object 当前选中图片的对象。
     */
    public Object getSelectObj() {
        int index = this.getSelectIndex();
        if (index > 0) {
            ListItem li = (ListItem) this.content.elementAt(index);
            if (li != null) {
                return li.obj;
            }
        }
        return null;
    }

    /**
     * 移除当前选中的图片。
     * @return int 当前选中图片对应的id。
     */
    public int removeCurrentSelected() {
        int id = this.getSelectId();
        if (id > 0) {
            this.removeById(id);
        }
        return -1;
    }

    /**
     * 移除指定id的图片。
     * @param id int 指定的id。
     */
    public void removeById(int id) {
        boolean process = false;
        for (int i = 0; i < this.content.size(); i++) {
            ListItem li = (ListItem) this.content.elementAt(i);
            if (li.id == id) {
                this.content.removeElement(li);
                process = true;
            }
        }
        if (process) {
            this.calcuateStrollbar();
            this.notifyItemListener();
        }
    }

    /**
     * 移除所有的图片。
     */
    public void removeAllContent() {
        this.drawBase = 0;
        this.xIndex = -1;
        this.yIndex = -1;
        this.content.removeAllElements();
        this.calcuateStrollbar();
    }

    /**
     * 获得当前图片块控件的图片数量。
     * @return int 图片块控件的图片数量。
     */
    public int getSize() {
        return this.content.size();
    }

    /**
     * 获得当前图片块一屏幕可以显示多少个图片。
     * @return int 可以显示的图片数量。
     */
    public int getDisSize() {
        return this.xDisCount * this.yDisCount;
    }

    /**
     * 设置一个图片的大小，单位为像素。
     * @param cellWidth int 图片的大小。
     */
    public void setCellWidth(int cellWidth) {
        if (cellWidth > 0 && this.cellWidth != cellWidth) {
            this.cellWidth = cellWidth;
            this.calcuateView();
            this.calcuateStrollbar();
        }
    }

    /**
     * 图片块绘制函数。
     * @param g Graphics 图形句柄。
     */
    public void draw(Graphics g) {
        if (!this.transparent) {
            g.setColor(this.bgColor);
            g.fillRect(0, 0, this.getRect().width, this.getRect().height);
        }
        g.translate(this.xDisOffset, this.yDisOffset);
        int baseIndex = this.drawBase * this.xDisCount;
        int count = Math.min(this.xDisCount * this.yDisCount, this.content.size() - baseIndex);
        int x = 0;
        int y = 0;
        for (int i = 0; i < count; i++) {
            ListItem li = (ListItem) this.content.elementAt(baseIndex + i);
            if (li != null) {
                Image icon = null;
                if (li.first1 instanceof Image) {
                    icon = (Image) li.first1;
                } else if (li.first1 instanceof DrawableItem) {
                    icon = (Image) ((DrawableItem) li.obj).getDrawableItem();
                }
                if (icon != null) {
                    int cx = g.getClipX();
                    int cy = g.getClipY();
                    int cw = g.getClipWidth();
                    int ch = g.getClipHeight();
                    g.setClip(x * (this.cellWidth + 1), y * (this.cellWidth + 1),
                            this.cellWidth, this.cellWidth);
                    g.drawImage(icon, x * (this.cellWidth + 1), y * (this.cellWidth + 1),
                            Graphics.LEFT | Graphics.TOP);
                    g.setClip(cx, cy, cw, ch);
                }
            }
            x++;
            if (x >= this.xDisCount) {
                x = 0;
                y++;
            }
        }
        if (super.getFocus()) {
            g.setColor(this.selectedColor);
            if (this.xIndex >= 0) {
                g.drawRect(this.xIndex * (this.cellWidth + 1), this.yIndex * (this.cellWidth + 1),
                        this.cellWidth - 1, this.cellWidth - 1);
                g.drawRect(this.xIndex * (this.cellWidth + 1) + 1, this.yIndex * (this.cellWidth + 1) + 1,
                        this.cellWidth - 3, this.cellWidth - 3);
            }
        }
        g.translate(-this.xDisOffset, -this.yDisOffset);
        g.setColor(this.strollbarLineColor);
        g.drawRect(this.effectiveWidth, 0, 4, this.getRect().height - 1);
        g.setColor(this.strollbarColor);
        if (this.content.size() != 0) {
            g.fillRect(this.effectiveWidth + 1, 1 + strollY, Window.STROLL_WIDTH - 2, strollHeight);
        } else {
            g.fillRect(this.effectiveWidth + 1, 1, Window.STROLL_WIDTH - 2, this.getRect().height - 2);
        }
        if (this.drawRect) {
            g.setColor(this.lineColor);
            g.drawRect(0, 0, this.getRect().width - 1, this.getRect().height - 1);
        }
    }

    /**
     * 图片块控件处理上下左右按键消息。
     * @param flag boolean 是按下还是抬起。
     * @param keyCode int 按键代码。
     * @param gameAction int 动作代码。
     * @return boolean 是否处理该事件。
     */
    public boolean keyEvent(boolean flag, int keyCode, int gameAction) {
        switch (gameAction) {
            case Canvas.LEFT: {
                if (flag) {
                    if (this.xIndex == 0) {
                        this.moveUp();
                    }
                    this.moveLeft();
                    this.notifyItemListener();
                }
                return true;
            }
            case Canvas.RIGHT: {
                if (flag) {
                    this.moveRight();
                    if (this.xIndex == 0) {
                        this.moveDown();
                    }
                    this.notifyItemListener();
                }
                return true;
            }
            case Canvas.UP:
                if (flag) {
                    this.moveUp();
                    this.notifyItemListener();
                }
                return true;
            case Canvas.DOWN: {
                if (flag) {
                    this.moveDown();
                    this.notifyItemListener();
                }
                return true;
            }
        }
        return false;
    }

    /**
     * 触笔事件处理函数，在图片块内的触笔事件都被处理。
     * @param ev Event 触笔事件。
     * @return boolean 是否处理该事件。
     */
    public boolean pointerEvent(Event ev) {
        boolean result = false;
        switch (ev.type) {
            case Event.POINTER_PRESSED:
                if (this.leftRect.collideWith(ev.param1, ev.param2)) { // 选中左侧区域
//                    this.isPointerSelected = true;
                    super.setPointerSelected(true);
                    this.pointerPressedY = ev.param2;
                    int px = (ev.param1 - this.getRect().leftUp.x - this.xDisOffset);
                    int py = (ev.param2 - this.getRect().leftUp.y - this.yDisOffset);
                    if (px >= 0 && py >= 0) {
                        int x = px / (this.cellWidth + 1);
                        int y = py / (this.cellWidth + 1);
                        int select = (this.drawBase + y) * this.xDisCount + x;
                        if (this.content.size() > select && x < this.xDisCount && y < this.yDisCount) {
                            this.pressSelectedIndex = this.yIndex * this.xDisCount + this.xIndex;
                            this.xIndex = x;
                            this.yIndex = y;
                            if (this.itemListener != null) {
                                if (super.getFocus()) {
                                    ListItem li = (ListItem) this.content.elementAt(this.getSelectIndex());
                                    if (li != null) {
                                        this.itemListener.pointerSelected(li.id, li.obj);
                                    }
                                }
                            }
                        }
                    }
                    result = true;
                } else if (this.getRect().collideWith(ev.param1, ev.param2)) { // 选中右侧滚动条
//                    this.isPointerSelected = true;
                    super.setPointerSelected(true);
                    this.pointerPressedY = ev.param2; // 记录触笔的垂直位置
                    if (ev.param2 < this.strollY) { // 计算选中的位置，然后判断向上还是向下
                        this.strollUp();
                    } else if (ev.param2 > this.strollY + this.strollHeight) {
                        this.strollDown();
                    }
                    result = true;
                }
                break;
            case Event.POINTER_RELEASED:
                if (super.getPointerSelected()) {
                    if (this.getRect().collideWith(ev.param1, ev.param2)) {
                        int px = (ev.param1 - this.getRect().leftUp.x - this.xDisOffset);
                        int py = (ev.param2 - this.getRect().leftUp.y - this.yDisOffset);
                        if (px >= 0 && py >= 0) {
                            int x = px / (this.cellWidth + 1);
                            int y = py / (this.cellWidth + 1);
                            int select = (this.drawBase + y) * this.xDisCount + x;
                            if (this.content.size() > select && x < this.xDisCount && y < this.yDisCount) {
                                if (this.pressSelectedIndex == select) {
                                    if (this.itemListener != null) {
                                        if (super.getFocus()) {
                                            ListItem li = (ListItem) this.content.elementAt(this.getSelectIndex());
                                            if (li != null) {
                                                this.itemListener.pointerDoubleSelected(li.id, li.obj);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        result = true;
                    }
//                    this.isPointerSelected = false;
                    super.setPointerSelected(false);
                }
                break;
            case Event.POINTER_DRAGGED:
                if (super.getPointerSelected()) {
                    if (this.leftRect.collideWith(ev.param1, ev.param2)) {
                        int px = (ev.param1 - this.getRect().leftUp.x - this.xDisOffset);
                        int py = (ev.param2 - this.getRect().leftUp.y - this.yDisOffset);
                        if (px >= 0 && py >= 0) {
                            int x = px / (this.cellWidth + 1);
                            int y = py / (this.cellWidth + 1);
                            int select = (this.drawBase + y) * this.xDisCount + x;
                            if (this.content.size() > select && x < this.xDisCount && y < this.yDisCount) {
                                this.pressSelectedIndex = this.yIndex * this.xDisCount + this.xIndex;
                                this.xIndex = x;
                                this.yIndex = y;
                                if (this.itemListener != null) {
                                    if (super.getFocus()) {
                                        ListItem li = (ListItem) this.content.elementAt(this.getSelectIndex());
                                        if (li != null) {
                                            this.itemListener.pointerSelected(li.id, li.obj);
                                        }
                                    }
                                }
                            }
                        }
                        result = true;
                    } else if (this.getRect().collideWith(ev.param1, ev.param2)) {
                        if (ev.param2 > this.strollY && ev.param2 < this.strollY + this.strollHeight) {
                            int y = ev.param2 - this.pointerPressedY;
                            if (Math.abs(y) > this.strollRowHeight) { // 触笔上下移动
                                this.pointerPressedY = ev.param2;
                                if (y > 0) {
                                    this.strollDown();
                                } else {
                                    this.strollUp();
                                }
                            }
                        }
                        result = true;
                    }
                }
                break;
        }
        return result;
    }

    /**
     * 通知监听器。
     */
    protected void notifyItemListener() {
        if (this.itemListener != null) {
            int index = this.getSelectIndex();
            if (index > 0) {
                ListItem li = (ListItem) this.content.elementAt(index);
                if (li != null) {
                    this.itemListener.keySelected(li.id, li.obj);
                }
            }
        }
    }

    /**
     * 重新计算行数和偏移，当行高或区域高度发生变化的时候，需要调用这个行数。
     */
    private void calcuateView() {
        if (this.effectiveWidth != this.getRect().width - Window.STROLL_WIDTH) {
            this.effectiveWidth = this.getRect().width - Window.STROLL_WIDTH;
            if (this.effectiveWidth < 0) {
                this.effectiveWidth = 0;
            }
        }
        this.xDisCount = this.effectiveWidth / (this.cellWidth + 1);
        this.yDisCount = this.getRect().height / (this.cellWidth + 1);
        this.xDisOffset = ((this.effectiveWidth % (this.cellWidth + 1)) + 1) >> 1;
        this.yDisOffset = ((this.getRect().height % (this.cellWidth + 1)) + 1) >> 1;
        if (this.xIndex >= this.xDisCount) {
            this.xIndex = this.xDisCount - 1;
        }
        if (this.yIndex >= this.yDisCount) {
            this.yIndex = this.yDisCount - 1;
        }
        if (this.drawBase > 0) {
            int withoutBaseSize = this.content.size() - this.drawBase * this.xDisCount;
            if (this.getDisSize() > withoutBaseSize) {
                this.drawBase -= ((this.getDisSize() - withoutBaseSize) + this.xDisCount - 1) / this.xDisCount;
                if (this.drawBase < 0) {
                    this.drawBase = 0;
                }
            }
        }
        this.calcuateStrollbar();
        this.leftRect.setRect(this.getRect());
        this.leftRect.width = this.effectiveWidth;
    }

    /**
     * 计算滚动条的y坐标和高度。
     */
    private void calcuateStrollbar() {
        if (this.xDisCount > 0 && this.yDisCount > 0) {
            int rows = (this.content.size() + this.xDisCount - 1) / this.xDisCount; // 一共有几行
            if (rows != 0) {
                this.strollY = (this.getRect().height - 2) * this.drawBase / rows;
                if (this.drawBase == rows - this.yDisCount) { // 当滚动条到最下面的时候，避免计算误差
                    this.strollHeight = this.getRect().height - 2 - this.strollY;
                } else {
                    this.strollHeight = (this.getRect().height - 2) * Math.min(this.yDisCount, rows) / rows;
                }
            } else {
                this.strollY = 0;
                this.strollHeight = this.getRect().height - 2;
            }
            if (this.content.size() > 0) {
                this.strollRowHeight = this.strollHeight / this.yDisCount;
            } else {
                this.strollRowHeight = this.getRect().height - 2;
            }
        } else {
            this.strollY = 0;
            this.strollHeight = this.getRect().height - 2;
            this.strollRowHeight = this.getRect().height - 2;
        }
    }

    /**
     * 检测指定位置是否有图片。
     * @param x int 位置横坐标。
     * @param y int 位置纵坐标。
     * @return boolean 是否有图片。
     */
    private boolean checkIndex(int x, int y) {
        if ((this.drawBase + y) * this.xDisCount + x < this.content.size()) {
            return true;
        }
        return false;
    }

    /**
     * 整个图片块向上移动。
     */
    private void strollUp() {
        if (this.drawBase > 0) {
            this.drawBase--;
            this.notifyItemListener();
            this.calcuateStrollbar();
        }
    }

    /**
     * 整个图片块向下移动。
     */
    private void strollDown() {
        if ((this.drawBase + this.yDisCount) * this.xDisCount < this.content.size()) {
            this.drawBase++;
            if (!this.checkIndex(this.xIndex, this.yIndex)) {
                this.xIndex = this.content.size() % this.xDisCount - 1;
            }
            this.notifyItemListener();
            this.calcuateStrollbar();
        }
    }

    /**
     * 选中位置向左移动。
     */
    private void moveLeft() {
        int tmp = this.content.size() - (this.drawBase + this.yIndex) * this.xDisCount;
        int rowMaxX = Math.min(this.xDisCount, tmp);
        this.xIndex = (this.xIndex - 1 + rowMaxX) % rowMaxX;
    }

    /**
     * 选中位置向右移动。
     */
    private void moveRight() {
        int tmp = this.content.size() - (this.drawBase + this.yIndex) * this.xDisCount;
        int rowMaxX = Math.min(this.xDisCount, tmp);
        this.xIndex = (this.xIndex + 1) % rowMaxX;
    }

    /**
     * 选中位置向上移动。
     */
    private void moveUp() {
        if (this.yIndex == 0) {
            if (this.drawBase == 0) {
                int maxRow = (this.content.size() + this.xDisCount - 1) / this.xDisCount;
                if (maxRow > this.yDisCount) {
                    this.yIndex = this.yDisCount - 1;
                    this.drawBase = (this.content.size() + this.xDisCount - 1) / this.xDisCount - this.yIndex - 1;
                    int tmp = this.content.size() - (this.drawBase + this.yIndex) * this.xDisCount;
                    this.xIndex = Math.min(this.xIndex, tmp - 1);
                    this.calcuateStrollbar();
                } else {
                    this.yIndex = maxRow - 1;
                    int tmp = this.content.size() - (this.drawBase + this.yIndex) * this.xDisCount;
                    this.xIndex = Math.min(this.xIndex, tmp - 1);
                }
            } else {
                this.drawBase--;
                this.calcuateStrollbar();
            }
        } else {
            this.yIndex = (this.yIndex - 1 + this.yDisCount) % this.yDisCount;
        }
    }

    /**
     * 选中位置向下移动。
     */
    private void moveDown() {
        if (this.yIndex == this.yDisCount - 1) {
            if ((this.drawBase + this.yDisCount) * this.xDisCount < this.content.size()) { // 如果base可以下移,则下移
                this.drawBase++;
                int tmp = (this.content.size() - (this.drawBase + this.yIndex) * this.xDisCount);
                this.xIndex = Math.min(this.xIndex, tmp - 1);
                this.calcuateStrollbar();
            } else { // 如果不能下移,则到首行
                this.drawBase = 0;
                this.yIndex = 0;
                this.calcuateStrollbar();
            }
        } else {
            int currentMaxRow = (this.content.size() - this.drawBase * this.xDisCount + this.yDisCount - 1) / this.xDisCount;
            this.yIndex = (this.yIndex + 1) % currentMaxRow;
            int tmp = (this.content.size() - (this.drawBase + this.yIndex) * this.xDisCount);
            this.xIndex = Math.min(this.xIndex, tmp - 1);
        }
    }
}
